package com.sytc.camera.dllinterface;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sytc.camera.util.AppConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 使用 JNA 加载 DLL 并对接口进行包装，方便使用
 */
@Component
public class CyFX3Device {

    private static final Logger log = LoggerFactory.getLogger(CyFX3Device.class);

    // 定义 CyApiDll 接口
    public interface CyApiDll extends Library {
        // 声明 DLL 中的函数
        Pointer NewDevice();  // 创建设备对象

        byte DeviceCount(Pointer device);  // 获取设备数量

        boolean Open(Pointer device, byte dev);  // 打开设备

        void Close(Pointer device);  // 关闭设备

        void DeleteDevice(Pointer device);  // 删除设备对象

        // 导出获取设备名称的函数
        void GetDeviceName(Pointer device, byte[] deviceName);  // 获取设备名称

        boolean IsBootLoaderRunning(Pointer device);  // 检查是否在运行

        // 第2个string会自动换成C++对应的char*
        int DownloadFw(Pointer device, String fileName, int mediaType);  // 下载固件

        // 声明获取 MaxPktSize 函数
        int GetMaxPktSize(Pointer device);  // 获取 MaxPktSize

        // 修改 InXferData 函数，传递 len 引用
        boolean InXferData(Pointer device, byte[] buf, IntByReference len);  // 传递 IntByReference 类型的 len

        // 设置传输超时时间
        void SetInTimeout(Pointer device, int timeout);
    }

    private final CyApiDll cyApiDll;
    private Pointer pointer;

    // 构造函数，加载 DLL 并初始化设备
    @Autowired
    public CyFX3Device(AppConfig appConfig) {
        this.cyApiDll = Native.load(appConfig.getCyapiDllPath(), CyApiDll.class);  // 加载 DLL
        this.pointer = this.cyApiDll.NewDevice();  // 创建设备对象
        log.info("CyApiDll 加载成功{}", appConfig.getCyapiDllPath());
    }

    // 获取设备数量
    public byte deviceCount() {
        return cyApiDll.DeviceCount(this.pointer);
    }

    // 打开设备
    public boolean open(int dev) {
        return cyApiDll.Open(this.pointer, (byte) dev);
    }

    // 关闭设备
    public void close() {
        if (this.pointer != null) {
            cyApiDll.Close(this.pointer);
        }
    }

    // 删除设备
    public void delete() {
        if (this.pointer != null) {
            cyApiDll.DeleteDevice(this.pointer);
            this.pointer = null;
        }
    }

    // 获取设备名称
    public String getDeviceName() {
        byte[] deviceName = new byte[256];  // 缓冲区
        cyApiDll.GetDeviceName(this.pointer, deviceName);
        return new String(deviceName).trim();  // 返回设备名称
    }

    // 检查 BootLoader 是否运行
    public boolean isBootLoaderRunning() {
        return cyApiDll.IsBootLoaderRunning(this.pointer);
    }

    // 下载固件
    public FX3_FWDWNLOAD_ERROR_CODE downloadFw(String filePath, FX3_FWDWNLOAD_MEDIA_TYPE mediaType) {
        return FX3_FWDWNLOAD_ERROR_CODE.fromInt(cyApiDll.DownloadFw(this.pointer, filePath, mediaType.getValue()));
    }

    // 获取 MaxPktSize
    public int getMaxPktSize() {
        return cyApiDll.GetMaxPktSize(this.pointer);
    }

    // 传输数据
    public TransferResult inXferData(byte[] buffer) {
        IntByReference lenRef = new IntByReference(buffer.length);
        boolean result = cyApiDll.InXferData(this.pointer, buffer, lenRef);
        return new TransferResult(result, lenRef.getValue());
    }

    // 设置传输超时
    public void setInTimeout(int timeout) {
        cyApiDll.SetInTimeout(this.pointer, timeout);
    }
}
